﻿/*
 * actionmgr.cpp
 *
 *  Created on: 2017年11月30日
 *      Author: work
 */

#include <dm/export.hpp>

#define DM_API_SCADA DM_API_EXPORT

#include <dm/scada/actionmgr.hpp>

#include <dm/scada/eventmgr.hpp>
#include <dm/scada/scadainfo.hpp>
#include <dm/scada/devicemgr.hpp>

#include <dm/os/log/logger.hpp>
#include <dm/datetime.hpp>

namespace dm{
namespace scada{

static const char* logModule = "CActionMgr.scada.dm";

CActionMgr::CActionMgr( CScada& scada ):CScada(scada),
		m_cfg(scada.actionInfos(),scada.info()->actionCount()){
}

CActionMgr& CActionMgr::ins(){
	static CActionMgr i( CScada::ins() );
	return i;
}

bool CActionMgr::setDesc( const index_t& idx,const char* str ){
	SActionInfo * p = m_cfg.at(idx);
	if( p ){
		p->desc = str;
		return true;
	}else
		return false;
}

bool CActionMgr::setLevel( const index_t& idx,SActionInfo::ELevel level ){
	SActionInfo* p = m_cfg.at(idx);
	if( p ){
		p->level = level;
		return true;
	}else
		return false;
}

bool CActionMgr::setFlagSave( const index_t& idx,bool s ){
	SActionInfo* p = m_cfg.at(idx);
	if( p ){
		p->setFlagSave(s);
		return true;
	}else
		return false;
}

bool CActionMgr::setFlagReportTimed( const index_t& idx,bool s ){
	SActionInfo* p = m_cfg.at(idx);
	if( p ){
		p->setFlagReportTimed(s);
		return true;
	}else
		return false;
}

/**
 * 根据动作的值，获取其文字描述。一般用于输出信息
 * @param idx
 * @param value
 * @return
 */
const char* CActionMgr::valueDesc( const index_t& idx,const CAction::value_t& value )const{
	switch( value ){
	case CAction::InvOff:
		return invOffDesc(idx);
		break;
	case CAction::Off:
		return offDesc(idx);
		break;
	case CAction::On:
		return onDesc(idx);
		break;
	case CAction::InvOn:
		return invOnDesc(idx);
	default:
		return "未定义状态";
	}
}

/**
 * 获取动作信息配置所属的设备索引
 * @param idx
 * @return 设备索引号
 * - Idx_Inv 设备未找到
 * - 其他 设备索引号
 */
index_t CActionMgr::deviceIndex( const index_t& idx )const{
	if( idx<0 || idx>=size() )
		return Idx_Inv;
	CDeviceMgr& d = CDeviceMgr::ins();

	for( index_t i=0;i<d.size();++i ){
		if( d.info(i)->posOfAction<=idx &&
                (d.info(i)->posOfAction+d.info(i)->sizeOfAction)>idx )
			return i;
	}

	return Idx_Inv;
}

const char* CActionMgr::deviceDesc( const index_t& idx )const{
	if( idx<0 || idx>=size() )
		return NULL;
	CDeviceMgr& d = CDeviceMgr::ins();

	for( index_t i=0;i<d.size();++i ){
		if( d.info(i)->posOfAction<=idx &&
                (d.info(i)->posOfAction+d.info(i)->sizeOfAction)>idx )
			return d.info(i)->desc.c_str();
	}

	return NULL;
}

/**
 * 更新动作信息的记录。
 * 一般应用程序不会直接调用本函数。
 * @see class CDeviceAgent
 * 如果成功，会在CEvent队列中增加新的记录。
 * @param idx 索引号
 * @param v  值
 * @param ts 记录产生时刻
 * @return
 */
bool CActionMgr::update( const index_t& idx,const CAction::value_t& value,const dm::CTimeStamp& ts ){
	if( idx<0 || idx>=size() ){
		log().warnning(THISMODULE "动作索引溢出%d",idx);	//! 如果参数idx不正常，可以查看logshow中的警告信息。
		return false;
	}

	CEvent e(CEvent::Action,idx,ts);
	e.value.action = value;
	CEventMgr::ins().gen(e);

	return true;
}

/**
 * 格式化输出动作配置信息
 * @param idx 动作信息的索引号
 * @param ostr 输出流
 */
void CActionMgr::printInfo( const index_t& idx,std::ostream& ostr )const{
	const SActionInfo* p = info(idx);
	if( p ){
		//! 正常输出内容包括：id,名字，描述，分状态描述，合状态描述，无效分状态描述，无效合状态描述，和级别。
		ostr <<"ID:"<<p->id
				<<" 名字:"<<p->name.c_str()
				<<" 描述:"<<p->desc.c_str()
				<<" 分状态:"<<CActionDescMgr::ins().desc(p->desc_off)
				<<" 合状态:"<<CActionDescMgr::ins().desc(p->desc_on)
				<<" 无效分状态:"<<CActionDescMgr::ins().desc(p->desc_invOff)
				<<" 无效合状态:"<<CActionDescMgr::ins().desc(p->desc_invOn)
				<<" 级别:"<<p->level
				<<" 存盘:";
		if( p->isFlagSave() )
			ostr <<"允许";
		else
			ostr <<"禁止";
	}else{
		ostr <<"无效索引("<<idx<<')';	//! 如果索引号异常，输出 无效索引。
	}
}

}
}


